import DxcrThree, { ThreejsUtill } from "@/package/dxcr-three";
import * as THREE from "three";

class CrackMap {
  dxcrThree;
  dom;
  legendDom;
  theme;
  group;
  xScale = 1;
  yScale = 0.6;
  zScale = 1;
  minX = 0;
  maxX = 0;
  minY = 0;
  maxY = 0;
  minZ = 0;
  maxZ = 0;
  minValue = 0;
  maxValue = 0;
  nameLabelList = [];
  config = {
    XZGridXlength: 8,
    XZGridYlength: 8,
    XYGridXlength: 8,
    XYGridYlength: 8,
    YZGridXlength: 8,
    YZGridYlength: 8,
  };
  _theme = {
    light: {
      lineColor: "#A2DCFF",
      axesColor: "#333333",
      axesFontColor: "#333333",
      XZGrid: {
        color: "#dddddd",
        lineColor: "#aaaaaa",
        opacity: 0.5,
      },
      XYGrid: {
        color: "#bbbbbb",
        lineColor: "#aaaaaa",
        opacity: 0.5,
      },
      YZGrid: {
        color: "#999999",
        lineColor: "#aaaaaa",
        opacity: 0.5,
      },
      legendFontColor: "#333333",
      legendTickLineColor: "#333333",
    },
    dark: {
      lineColor: "#A2DCFF",
      axesColor: "#ffffff",
      axesFontColor: "#ffffff",
      XZGrid: {
        color: "#ffffff",
        lineColor: "#aaaaaa",
        opacity: 0,
      },
      XYGrid: {
        color: "#dddddd",
        lineColor: "#aaaaaa",
        opacity: 0,
      },
      YZGrid: {
        color: "#bbbbbb",
        lineColor: "#aaaaaa",
        opacity: 0,
      },
      legendFontColor: "#ffffff",
      legendTickLineColor: "#ffffff",
    },
  };
  constructor(dom, { theme = "light" } = {}) {
    this.theme = theme;
    this.dom = dom;
    console.log("CrackTheme", theme);
    this.init();
  }
  init() {
    this.init3D();
  }
  init3D() {
    //render宽高
    let dxcrThree = new DxcrThree(this.dom, { cameraMode: 2 });
    // dxcrThree.setBackground(new THREE.Color(0x050e26));
    dxcrThree.setBackground(null);
    this.dxcrThree = dxcrThree;
    this.setColorLegend();
    this.initResize();
    // this.animate();
  }

  initResize() {
    let c = this;
    window.addEventListener("resize", () => {
      c.resize();
    });
  }

  resize() {
    this.dxcrThree.resize();
  }

  animate() {
    // let c = this;
    // ThreejsUtill.animateDelta((deltaTime) => {
    //   if (c.group) {
    //     let center = ThreejsUtill.getModelCenter(c.group);
    //     let size = ThreejsUtill.getModelSize(c.group);
    //     // 获取轴线的方向向量
    //     const lineDirection = new THREE.Vector3(1, 0, 0).normalize();
    //     const startDirection = new THREE.Vector3(
    //       center.x + size.x / 2,
    //       center.y,
    //       center.z + size.z / 2
    //     )
    //     // const startDirection = new THREE.Vector3(0, 0, 0);
    //     //相机方向
    //     const cameraDirection = new THREE.Vector3();
    //     c.dxcrThree.camera.getWorldPosition(cameraDirection);
    //     // 计算相机与线段之间的方向向量
    //     const dirToCamera = new THREE.Vector3().subVectors(
    //       cameraDirection,
    //       startDirection
    //     ).normalize();
    //     // 计算线段方向与相机方向之间的角度
    //     const dotProduct = dirToCamera.dot(lineDirection);
    //     // 计算夹角的余弦值
    //     const rad = Math.acos(dotProduct);
    //     let deg = rad * (180 / Math.PI);
    //     deg = -(deg) - 45
    //       console.log(deg);
    //     for (let nameLabel of c.nameLabelList) {
    //       let inner = nameLabel.element.children[0];
    //       inner.style.transform = `rotate(${deg}deg)`;
    //     }
    //   }
    // });
  }

  getTheme() {
    return this._theme[this.theme];
  }

  setCrackData(crackData) {
    let c = this;
    //删除上次的
    if (c.group) {
      c.nameLabelList = [];
      c.dxcrThree.remove(c.group);
    }
    // 计算最小和最大缝宽，用于颜色映射
    const widths = crackData.flatMap((fracture) => fracture.map((p) => p[4]));
    const minWidth = Math.min(...widths);
    const maxWidth = Math.max(...widths);
    c.maxValue = maxWidth;
    // c.minValue = minWidth;
    c.minValue = 0;
    c.setColorLegend();
    // console.log("minWidth", minWidth);
    // console.log("maxWidth", maxWidth);

    const group = new THREE.Group();

    // 创建材质
    const material = new THREE.MeshBasicMaterial({
      vertexColors: true,
      side: THREE.DoubleSide,
      transparent: true,
      opacity: 0.9,
    });

    //获取所有原始坐标范围
    let minX = Infinity,
      maxX = -Infinity,
      minY = Infinity,
      maxY = -Infinity,
      minZ = Infinity,
      maxZ = -Infinity;

    crackData.forEach((fracture) => {
      fracture.forEach(([x, y, zMax, zMin]) => {
        if (x < minX) minX = x;
        if (x > maxX) maxX = x;

        if (y < minY) minY = y;
        if (y > maxY) maxY = y;

        if (zMin < minZ) minZ = zMin;
        if (zMax > maxZ) maxZ = zMax;
      });
    });
    console.log('minX',minX)
    c.minX = minX
    c.maxX = maxX
    c.minY = minY
    c.maxY = maxY
    c.minZ = minZ
    c.maxZ = maxZ

    crackData.forEach((fracture) => {
      let vertices = [];
      let colors = [];
      fracture.forEach((point) => {
        const [x, y, zMax, zMin, width] = point;
        // 归一化
        const nx = ThreejsUtill.normalize(x, minX, maxX, c.xScale);
        const ny = ThreejsUtill.normalize(y, minY, maxY,c.zScale);
        const nzMax = ThreejsUtill.normalize(zMax, minZ, maxZ,c.yScale);
        const nzMin = ThreejsUtill.normalize(zMin, minZ, maxZ,c.yScale);

        //获得颜色
        const color = c.getColor(width, minWidth, maxWidth);
        //添加顶点
        vertices.push(nx, nzMin, ny);
        vertices.push(nx, nzMax, ny);

        //添加顶点颜色
        colors.push(color.r, color.g, color.b);
        colors.push(color.r, color.g, color.b);
      });

      // 创建 BufferGeometry
      const geometry = new THREE.BufferGeometry();
      geometry.setAttribute(
        "position",
        new THREE.BufferAttribute(new Float32Array(vertices), 3)
      );
      geometry.setAttribute(
        "color",
        new THREE.BufferAttribute(new Float32Array(colors), 3)
      );
      //设置顶点顺序
      let indices = [];
      for (let i = 0; i < vertices.length / 3 - 2; i++) {
        indices.push(i, i + 1, i + 2);
      }
      geometry.setIndex(indices);

      // 创建 Mesh 并添加到场景
      const mesh = new THREE.Mesh(geometry, material);
      group.add(mesh);
    });

    const box = new THREE.Box3(
      new THREE.Vector3(0, 0, 0), // 最小点
      new THREE.Vector3(c.xScale, c.yScale, c.zScale) // 最大点
    );

    c.setLine(group,box);
    c.setGrid(group,box);

    c.dxcrThree.add(group);

    //加到缓存
    group.traverse((child) => {
      if (child.name == "nameLabel") {
        c.nameLabelList.push(child);
      }
    });

    if (!this.group) {
      ThreejsUtill.adjustCameraToFitModel(
        c.dxcrThree.camera,
        group,
        c.dxcrThree.orbitControls,
        {
          angle: { azimuth: 45, elevation: 30 },
          scaleFactor: 1.5,
        }
      );
    }

    this.group = group;
  }
  setGrid(group,box) {
    let c = this;
    // 获取 group 的包围盒，计算最小 Y 值
    // const box = new THREE.Box3().setFromObject(group);
    let center = ThreejsUtill.getModelCenter(box);
    let size = ThreejsUtill.getModelSize(box);
    let gridSize = Math.max(size.x, size.y, size.z);

    console.log("center", center);
    console.log("size", size);
    console.log("gridSize", gridSize);
    // === XZ 平面网格 ===
    const gridHelperXZ = ThreejsUtill.createGrid({
      width: gridSize,
      height: gridSize,
      divisionsX: c.config.XZGridXlength,
      divisionsY: c.config.XZGridYlength,
      color: c.getTheme().XZGrid.color,
      lineColor: c.getTheme().XZGrid.lineColor,
      opacity: c.getTheme().XZGrid.opacity,
    });
    gridHelperXZ.position.x = center.x;
    gridHelperXZ.position.y = box.min.y;
    gridHelperXZ.position.z = center.z;
    group.add(gridHelperXZ);

    // === XY 平面网格 ===
    const gridHelperXY = ThreejsUtill.createGrid({
      width: size.y,
      height: gridSize,
      divisionsX: c.config.XYGridXlength,
      divisionsY: c.config.XYGridYlength,
      color: c.getTheme().XYGrid.color,
      lineColor: c.getTheme().XYGrid.lineColor,
      opacity: c.getTheme().XYGrid.opacity,
    });
    gridHelperXY.rotation.x = Math.PI / 2;
    gridHelperXY.rotation.y = Math.PI / 2;
    gridHelperXY.position.x = center.x;
    gridHelperXY.position.y = box.min.y + size.y / 2;
    gridHelperXY.position.z = center.z - gridSize / 2;
    group.add(gridHelperXY);

    // === YZ 平面网格 ===
    const gridHelperYZ = ThreejsUtill.createGrid({
      width: size.y,
      height: gridSize,
      divisionsX: c.config.YZGridXlength,
      divisionsY: c.config.YZGridYlength,
      color: c.getTheme().YZGrid.color,
      lineColor: c.getTheme().YZGrid.lineColor,
      opacity: c.getTheme().YZGrid.opacity,
    });
    gridHelperYZ.rotation.z = Math.PI / 2; // 旋转 90° 使其平行于 YZ 平面
    gridHelperYZ.position.x = center.x - gridSize / 2;
    gridHelperYZ.position.y = box.min.y + size.y / 2;
    gridHelperYZ.position.z = center.z;
    group.add(gridHelperYZ);

    //构建坐标轴数组
    let segments = 8;
    let axesXDataList = [];
    let axesZDataList = [];
    let axesYDataList = [];
    for (let i = 0; i < segments + 1; i++) {
      let axesXData = (
        c.minX 
        +
        (c.maxX - c.minX) * i / segments
      ).toFixed(2);
      axesXDataList.push(axesXData);
      let axesZData = (
        c.minZ 
        +
        (c.maxZ - c.minZ) * i / segments
      ).toFixed(2);
      axesZDataList.push(axesZData);
      let axesYData = (
        c.minY
         + 
         (c.maxY - c.minY) * i / segments
        ).toFixed(2);
      axesYDataList.push(axesYData);
    }

    const tickLength = 0.05
    // === X坐标轴 ===
    const axesX = ThreejsUtill.createAxes({
      length: gridSize,
      data: axesXDataList,
      tickLength:tickLength,
      name: "井筒方向/m",
      // nameSpace: [20, -10],
      nameSpace: [0.3, -0.1],
      fontColor: c.getTheme().axesFontColor,
      color: c.getTheme().axesColor,
    });
    axesX.position.x = center.x - gridSize / 2;
    axesX.position.y = box.min.y;
    axesX.position.z = center.z + gridSize / 2;
    group.add(axesX);

    // === Z坐标轴 ===
    const axesZ = ThreejsUtill.createAxes({
      length: gridSize,
      data: axesZDataList,
      tickLength:tickLength,
      name: "裂缝延伸方向/m",
      nameSpace: [0.4, -0.1],
      direction: "vertical",
      fontColor: c.getTheme().axesFontColor,
      color: c.getTheme().axesColor,
    });
    axesZ.rotation.y = Math.PI / 2;
    axesZ.position.x = center.x + gridSize / 2;
    axesZ.position.y = box.min.y;
    axesZ.position.z = center.z + gridSize / 2;
    group.add(axesZ);
    // === Y 坐标轴 ===
    const axesY = ThreejsUtill.createAxes({
      length: size.y,
      data: axesYDataList,
      tickLength:tickLength,
      name: "缝高方向/m",
      nameSpace: [0.4, 0],
      direction: "vertical",
      fontColor: c.getTheme().axesFontColor,
      color: c.getTheme().axesColor,
    });
    axesY.rotation.z = Math.PI / 2;
    axesY.rotation.y = Math.PI / 2;
    axesY.position.x = center.x + gridSize / 2;
    axesY.position.y = box.min.y;
    axesY.position.z = center.z - gridSize / 2;
    group.add(axesY);
  }

  setLine(group,box) {
    let c = this;
    // 创建穿插的线条
    const lineGeometry = new THREE.BufferGeometry();

    const lineVertices = new Float32Array([
      0,
      c.yScale / 2,
      c.zScale / 2,
      c.xScale,
      c.yScale / 2,
      c.zScale / 2,
    ]);
    lineGeometry.setAttribute(
      "position",
      new THREE.BufferAttribute(lineVertices, 3)
    );
    console.log(lineVertices)

    // 线的材质
    const lineMaterial = new THREE.LineBasicMaterial({
      color: c.getTheme().lineColor,
    });

    // 创建线并添加到 Group 中
    const line = new THREE.Line(lineGeometry, lineMaterial);
    group.add(line);
  }

  //渐变色数组
  rainbowColors = [
    [255, 0, 0], // 红色
    [255, 165, 0], // 橙色
    [255, 255, 0], // 黄色
    [0, 255, 0], // 绿色
    [0, 255, 255], // 青色
    [0, 0, 255], // 蓝色
    [75, 0, 130], // 靛蓝色
    [148, 0, 211], // 紫色
  ];
  // 获取颜色
  getColor(value, min, max) {
    // 计算归一化比例
    let ratio = 1 - (value - min) / (max - min);
    ratio = Math.max(0, Math.min(1, ratio));

    // 计算颜色索引
    let index = ratio * (this.rainbowColors.length - 1);
    let lowIndex = Math.floor(index);
    let highIndex = Math.ceil(index);

    // 计算插值比例
    let t = index - lowIndex;

    // 获取颜色
    let c1 = this.rainbowColors[lowIndex];
    let c2 = this.rainbowColors[highIndex];

    // 线性插值计算颜色
    let r = Math.round(c1[0] + t * (c2[0] - c1[0]));
    let g = Math.round(c1[1] + t * (c2[1] - c1[1]));
    let b = Math.round(c1[2] + t * (c2[2] - c1[2]));
    return new THREE.Color(`rgb(${r}, ${g}, ${b})`);
  }

  // 添加颜色图例
  setColorLegend() {
    let c = this;
    if (c.legendDom) {
      c.legendDom.parentNode.removeChild(c.legendDom);
    }
    // 创建外层 div
    const legendDom = document.createElement("div");
    c.legendDom = legendDom;
    legendDom.id = "legend";
    Object.assign(legendDom.style, {
      position: "absolute",
      width: "15px",
      height: "120px",
      border: "1px solid #ffffff",
      right: "20px",
      bottom: "20px",
    });

    // 创建 6 个刻度
    const totalTicks = 6;
    const step = (c.maxValue - c.minValue) / (totalTicks - 1); // 计算每个刻度之间的间隔

    // 创建刻度并设置样式
    for (let i = 0; i < totalTicks; i++) {
      const tickValue = c.minValue + i * step; // 当前刻度值

      // 格式化刻度值
      const formattedTickValue = Number.isInteger(tickValue)
        ? tickValue
        : tickValue.toFixed(1);

      const tickLineDom = document.createElement("div");
      Object.assign(tickLineDom.style, {
        position: "absolute",
        bottom: `${i * (100 / (totalTicks - 1))}%`, // 根据比例设置位置
        left: "0px",
        transform: "translate(-100%, 50%)",
        width: "5px",
        height: "1px",
        background: c.getTheme().legendTickLineColor,
      });
      legendDom.appendChild(tickLineDom);

      const tickValueDom = document.createElement("div");
      tickValueDom.textContent = formattedTickValue; // 设置刻度文本
      // 设置刻度的样式
      Object.assign(tickValueDom.style, {
        position: "absolute",
        bottom: `${i * (100 / (totalTicks - 1))}%`, // 根据比例设置位置
        left: "-10px",
        transform: "translate(-100%, 50%)",
        fontSize: "12px",
        color: c.getTheme().legendFontColor,
      });

      legendDom.appendChild(tickValueDom);
    }

    const nameDom = document.createElement("div");
    nameDom.textContent = "缝宽/mm";
    Object.assign(nameDom.style, {
      position: "absolute",
      top: "50%",
      right: "-5px",
      transform: "translate(100%, -50%)",
      fontSize: "14px",
      fontWeight: "bold",
      writingMode: "vertical-rl",
      color: c.getTheme().legendFontColor,
    });

    // 组装结构
    legendDom.appendChild(nameDom);

    // 将 legend 添加到 body
    this.dom.appendChild(legendDom);

    // 创建画布
    const canvas = document.createElement("canvas");
    // 设置 canvas 的宽高
    canvas.style.width = "100%";
    canvas.style.height = "100%";

    const ctx = canvas.getContext("2d");

    // 创建线性渐变
    const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
    const numColors = this.rainbowColors.length;

    // 按比例均匀分布颜色
    for (let i = 0; i < numColors; i++) {
      const stopPosition = i / (numColors - 1);
      const color = `rgb(${this.rainbowColors[i][0]}, ${this.rainbowColors[i][1]}, ${this.rainbowColors[i][2]})`;
      gradient.addColorStop(stopPosition, color);
    }

    // 绘制渐变矩形
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 清空并添加新画布
    legendDom.appendChild(canvas);
  }
}

export default CrackMap;
